/* * Alien Chase 2013 Chema Edition -- a remake of Alien Chase 2013 by danirod * Copyright (C) 2013 Dani Rodríguez <danirod@outlook.com> Twitter: @danirod93 * & José María Valera Reales <chemaclass@outlook.es> Twitter: @Chemaclass * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package tk.makigas.chase; import static tk.makigas.chase.AlienChase.random; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import tk.makigas.chase.actor.AlienActor; import tk.makigas.chase.actor.BarraActor; import tk.makigas.chase.actor.BulletActor; import tk.makigas.chase.actor.EscudoActor; import tk.makigas.chase.actor.NaveActor; import tk.makigas.chase.actor.PadActor; import tk.makigas.chase.actor.PuntuacionActor; import tk.makigas.chase.listeners.InputAndroidMoveListener; import tk.makigas.chase.listeners.InputAndroidReloadListener; import tk.makigas.chase.listeners.InputAndroidShootListener; import tk.makigas.chase.listeners.InputDesktopListener; import com.badlogic.gdx.Application.ApplicationType; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.audio.Sound; import com.badlogic.gdx.graphics.GL11; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.Image; /** * Pantalla de juego principal. * * @author danirod * @author chemaclass */ public class GameplayScreen extends AbstractScreen { /** Escenario usado por el juego. */ private Stage stage; /** Nave usada por el jugador. */ private NaveActor nave; /** Escudo de la Tierra. */ private List<EscudoActor> escudos; /** HUD usado para mostrar la vida de la nave. */ private BarraActor vidaNave; /** Pads usados para controlar el juego en Android. */ private PadActor padArriba, padAbajo, padDerecha, padIzquierda, padShoot, padRecargar; /** Puntuación. */ private PuntuacionActor puntuacion; /** Lista de aliens. */ private List<AlienActor> aliens; /** Activar sonido de los efectos. */ private static boolean sonidoEfectos = false; /** Activar sonido del ambiente. */ private static boolean sonidoFondo = true; /** Estados en los que se puede encontrar el juego. */ public enum State { RUNNING, PAUSED, LOST } /** Estado del juego. */ private static State state = State.PAUSED; public GameplayScreen(AlienChase game) { super(game); } @Override public void show() { if (sonidoFondo) { AlienChase.MANAGER.get("sound/corazon.ogg", Sound.class).loop(); } // Creamos un nuevo escenario y lo asociamos a la entrada. int width = Gdx.graphics.getWidth(); int height = Gdx.graphics.getHeight(); stage = new Stage(width, height, true, game.SB); Gdx.input.setInputProcessor(stage); // Crear fondo. Image imgFondo = new Image(AlienChase.MANAGER.get("images/fondo.png", Texture.class)); imgFondo.setFillParent(true); stage.addActor(imgFondo); // Creamos una nave. nave = new NaveActor(stage); nave.setPosition(stage.getWidth() / 2 - nave.getHeight() / 2, 10); // Creamos los HUD de las naves. vidaNave = new BarraActor(stage, nave); vidaNave.setPosition(stage.getWidth() - 150, stage.getHeight() - 20); // Creamos la puntuación. puntuacion = new PuntuacionActor(stage, new BitmapFont(), nave); puntuacion.setPosition(10, stage.getHeight() - 10); // Creamos los escudos. crearEscudos(); // Creamos los aliens. crearAliens(); // Preparamos los listeners crearListeners(); state = State.RUNNING; } /** Creamos los sistemas de entrada/salida */ private void crearListeners() { // Creamos los sistemas de entrada. En escritorio tendremos que usar // un listener que lo hace todo, mientras que para Android tendremos // que usar tres botones asociados cada uno a algo. if (Gdx.app.getType() == ApplicationType.Desktop) { stage.setKeyboardFocus(nave); // damos foco a nave. nave.addListener(new InputDesktopListener(game, nave)); } else if (Gdx.app.getType() == ApplicationType.Android) { // Creamos los pads. padArriba = new PadActor(0, 0); padAbajo = new PadActor(1, 0); padDerecha = new PadActor(0, 2); padIzquierda = new PadActor(1, 2); padShoot = new PadActor(0, 1); padRecargar = new PadActor(0, 1); // Los colocamos. padArriba.setPosition(70, 70); padAbajo.setPosition(70, 10); padDerecha.setPosition(130, 10); padIzquierda.setPosition(10, 10); padShoot.setPosition(stage.getWidth() - 70, 10); padRecargar.setPosition(stage.getWidth() - 130, 10); // Añadimos los listeners. padArriba.addListener(new InputAndroidMoveListener(nave, 250f, false)); padAbajo.addListener(new InputAndroidMoveListener(nave, -250f, false)); padDerecha.addListener(new InputAndroidMoveListener(nave, 250f, true)); padIzquierda.addListener(new InputAndroidMoveListener(nave, -250f, true)); padShoot.addListener(new InputAndroidShootListener(nave)); padRecargar.addListener(new InputAndroidReloadListener(nave)); // Los añadimos al escenario. stage.addActor(padArriba); stage.addActor(padAbajo); stage.addActor(padDerecha); stage.addActor(padIzquierda); stage.addActor(padShoot); stage.addActor(padRecargar); } } @Override public void render(float delta) { Gdx.gl.glClear(GL11.GL_COLOR_BUFFER_BIT); if (state.equals(State.RUNNING)) { stage.act(); // Revisamos las colisiones colisionesAliensNaveYEscudos(); colisionesNaveAliens(); // Revisamos si destruimos a todos los aliens if (aliens.size() <= 0) win(); } else if (state.equals(State.PAUSED)) { } else if (state.equals(State.LOST)) { game.setScreen(game.GAMEOVER); } stage.draw(); } /** Ganar partida */ private void win() { if (sonidoEfectos) AlienChase.MANAGER.get("sound/siguiente-nivel.mp3", Sound.class) .play(); // Incrementamos la velocidad de los aliens en x de manera aleatoria AlienActor.sumMovimientoX(random(0, 6)); // Cada 3 niveles estableceremos de nuevo la velocidad en range(3, 8) if (puntuacion.getNivel() % 3 == 0) { AlienActor.setMovimientoX(random(3, 8)); } nave.limpiarBullets(); puntuacion.subirNivel(); // Creamos los aliens. crearAliens(); } /** Colisiones de los disparos de la nave con los aliens */ private void colisionesNaveAliens() { Iterator<BulletActor> itBullets = nave.getBullets().iterator(); // Iteramos por las balas de nuestra nave while (itBullets.hasNext()) { BulletActor bullet = itBullets.next(); Iterator<AlienActor> itAliens = aliens.iterator(); // Iteramos por la lista de aliens while (itAliens.hasNext()) { AlienActor alien = itAliens.next(); // Si existe una colisión entre ambos if (bullet.collision(alien)) { if (sonidoEfectos) AlienChase.MANAGER.get("sound/hit-alien.wav", Sound.class).play(); // Eliminamos los actores alien/bala del stage stage.getRoot().removeActor(alien); stage.getRoot().removeActor(bullet); // borramos todas sus balas del stage alien.limpiarBullets(); // Eliminamos los actores alien/bala de las listas itAliens.remove(); AlienActor.nAliensVivos--;// Le restamos 1 al número de // Aliens vivos try { itBullets.remove(); } catch (java.lang.IllegalStateException e) { // Ocurre cuando dos balas colisionan al mismo tiempo en // un mismo alien } nave.subirPuntuacion(); } } } } /** Colisiones de los disparos de cada alien con la nave y los escudos */ private void colisionesAliensNaveYEscudos() { Iterator<AlienActor> itAliens = aliens.iterator(); // Iteramos por la lista de aliens while (itAliens.hasNext()) { Iterator<BulletActor> itBullets = itAliens.next().getBullets() .iterator(); // Iteramos por la lista de sus balas while (itBullets.hasNext()) { BulletActor bullet = itBullets.next(); // Se produce una colisión entre una bala_alien/nave if (bullet.collision(nave)) { stage.getRoot().removeActor(bullet); itBullets.remove(); nave.sumHealth(-0.35f); if (sonidoEfectos) AlienChase.MANAGER.get("sound/hit-nave.ogg", Sound.class).play(); if (nave.getHealth() <= 0) game.setScreen(game.GAMEOVER); } else { Iterator<EscudoActor> itEscudos = escudos.iterator(); // Iteramos por todos los escudos while (itEscudos.hasNext()) { EscudoActor escudo = itEscudos.next(); // Se produce una colisión entre bala_alien/escudo if (bullet.collision(escudo)) { if (sonidoEfectos) AlienChase.MANAGER.get("sound/hit-escudo.wav", Sound.class).play(); stage.getRoot().removeActor(bullet); try { itBullets.remove(); } catch (java.lang.IllegalStateException e) { // Ocurre cuando dos balas colisionan al mismo // tiempo en un mismo alien } } } } } } } /** Creamos los escudos */ private void crearEscudos() { escudos = new ArrayList<EscudoActor>(); // int numEscudos = EscudoActor.NUM_ESCUDOS; int numEscudos = 4; for (int i = 0; i < numEscudos; i++) { float x = 50 + i * 128; float y = 110; EscudoActor escudo = new EscudoActor(stage); escudo.setPosition(x, y); escudos.add(escudo); } } /** Creamos los aliens */ private void crearAliens() { aliens = new ArrayList<AlienActor>(); int colum = AlienActor.NUM_COLUM; int filas = AlienActor.NUM_FILAS; // int colum = 1,filas = 1; // Creamos los aliens for (int i = 0; i < colum; i++) { for (int j = 0; j < filas; j++) { AlienActor alien = new AlienActor(stage); float x = 20 + (i * 50); float y = stage.getHeight() - (50 + (j * 40)); alien.setPosition(x, y); aliens.add(alien); } } } /** Pausar el juego. */ public static void pausar() { state = State.PAUSED; } /** Continuar el juego. */ public static void continuar() { state = State.RUNNING; } /** Juego perdido. */ public static void gameOver() { state = State.LOST; } public static State getEstado() { return state; } @Override public void hide() { Gdx.input.setInputProcessor(null); if (sonidoFondo) { AlienChase.MANAGER.get("sound/corazon.ogg", Sound.class).stop(); } } @Override public void dispose() { stage.dispose(); } @Override public void resize(int width, int height) { stage.setViewport(width, height, true); vidaNave.setPosition(stage.getWidth() - 150, stage.getHeight() - 20); if (Gdx.app.getType() == ApplicationType.Android && padShoot != null) padShoot.setPosition(stage.getWidth() - 50, 10); } public static boolean isSonidoEfectos() { return sonidoEfectos; } public static void setSonidoEfectos(boolean soundEffects) { GameplayScreen.sonidoEfectos = soundEffects; } public static boolean isSonidoFondo() { return sonidoFondo; } public static void setSonidoFondo(boolean soundBack) { GameplayScreen.sonidoFondo = soundBack; } }